-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
signal: custom exit code status for interceptor #5636
Conversation
Hi @carlaKC ! I have solved the issue, ensured the CI checks pass with a PR on personal fork 😃 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Looking good
be526ce
to
1057f6d
Compare
Hey @carlaKC Implemented and amended the suggested changes! |
1057f6d
to
1764854
Compare
Force pushed from 1057f6d to 1764854 to fix a lint issue reported by Travis. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick turnaround!
Two things:
- Why not just pass a pointer to the
Interceptor
around? - If we're going to use a channel for the exit code, it needs to always have a value sent in so that the caller can read the exit code value without getting blocked.
@@ -75,7 +75,7 @@ func Start(extraArgs string, rpcReady Callback) { | |||
|
|||
// Load the configuration, and parse the extra arguments as command | |||
// line options. This function will also set up logging properly. | |||
loadedConfig, err := lnd.LoadConfig(shutdownInterceptor) | |||
loadedConfig, err := lnd.LoadConfig(*shutdownInterceptor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we want to dereference here? Can't we just pass a pointer in?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially tried passing it directly to figure out the LoadConfig does not accpet and reference to Interceptor. I was not sure which all aspects of LND would be using the loadConfig as it seems very important to parse the user configs, hence i decided to go the safe way and passed a de-referenced interceptor
Line 569 in 9e8b9cc
func LoadConfig(interceptor signal.Interceptor) (*Config, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can bump LoadConfig
to accept a pointer 👍
This commit adds an ability to interceptor to have custom exit status-codes for interceptor that allows to exit after an graceful exit Signed-off-by: DarthBenro008 <[email protected]>
Signed-off-by: DarthBenro008 <[email protected]>
1764854
to
37a76a1
Compare
Hey @carlaKC , I have implemented the recommended changes and have resolved the conversations 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shaping up nicely!
if !atomic.CompareAndSwapInt32(&started, 0, 1) { | ||
return Interceptor{}, errors.New("intercept already started") | ||
return &Interceptor{}, errors.New("intercept already started") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can just return nil here, safe to assume that it won't be used when there's a non-nil error :)
@@ -34,9 +34,10 @@ func main() { | |||
// Call the "real" main in a nested manner so the defers will properly | |||
// be executed in the case of a graceful shutdown. | |||
if err = lnd.Main( | |||
loadedConfig, lnd.ListenerCfg{}, shutdownInterceptor, | |||
loadedConfig, lnd.ListenerCfg{}, *shutdownInterceptor, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still dereferencing here?
@@ -34,20 +34,24 @@ type Interceptor struct { | |||
|
|||
// quit is closed when instructing the main interrupt handler to exit. | |||
quit chan struct{} | |||
|
|||
// exitCode is the exit code status when the main interrupt handler exits | |||
exitCode chan int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth adding a comment here that we must set a value here, otherwise the GetExitCode
function will block.
shutdown() | ||
|
||
case <-c.quit: | ||
log.Infof("Gracefully shutting down.") | ||
close(c.shutdownChannel) | ||
signal.Stop(c.interruptChannel) | ||
// Adding exit status code 0 as this will quit after graceful shutdown | ||
c.setExitCode(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to set an exit code here? I think we can only hit this case if we've called shutdown
in one of the other cases?
We can't send multiple values into the channel otherwise we'll end up blocked. I think it's worth adding a comment above <-c.quit
that we only reach this case once shutdown has been called.
@@ -75,7 +75,7 @@ func Start(extraArgs string, rpcReady Callback) { | |||
|
|||
// Load the configuration, and parse the extra arguments as command | |||
// line options. This function will also set up logging properly. | |||
loadedConfig, err := lnd.LoadConfig(shutdownInterceptor) | |||
loadedConfig, err := lnd.LoadConfig(*shutdownInterceptor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can bump LoadConfig
to accept a pointer 👍
@DarthBenro008 any updates here? |
@DarthBenro008, remember to re-request review from reviewers when ready |
Closing due to inactivity. |
Replaced by #8659 |
Outline and Challenge
This issue was required
lnd
to exit withstatus code 1
where there was an request toshutdownRequestChannel
lnd/signal/signal.go
Lines 100 to 102 in 52767a7
The challenge was that we had to do an
os.exit(1)
after an graceful shutdown.An graceful shutdown occurs when all the deferred go function in the
Main()
function clean up, but there is no way that we can pass the data or tell the function that cleans up last to exit with a particular status code.Approach
I pulled the defer function of
Main()
outside fromlnd
package and put it undercmd/lnd.go
where theMain()
get's called (giving us parental access to shutdownInterceptor) and added an additional parameter to Interceptor struct so that we can pass data when an graceful shutdown has occurred.I am passing a pointer reference in-order to retain the modifications (setting exit code) in the Intercept struct in
goroutines
.Steps to test this PR
./lnd-debug --rpclisten=localhost:10001 --listen=localhost:10011 --restlisten=localhost:8001 --debuglevel=debug --healthcheck.chainbackend.backoff=1s --healthcheck.chainbackend.interval=1m0s --healthcheck.chainbackend.timeout=3s
./lncli-debug --rpcserver=localhost:10001 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon unlock
ctrl+c
and shutdown yourbitcoind
serverlnd
will exit gracefully with an exit status code 1Pull Request Checklist